package com.example.service.Impl;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.common.Result;
import com.example.common.UsernameAuthenticationToken;
import com.example.common.enums.KeyEnum;
import com.example.common.enums.ResultCodeEnum;
import com.example.constant.JwtClaimsConstant;
import com.example.common.exception.CustomException;
import com.example.mapper.AdminMapper;
import com.example.pojo.dto.PasswordDTO;
import com.example.pojo.entity.Account;
import com.example.pojo.entity.Admin;
import com.example.pojo.utils.LoginUser;
import com.example.properties.JwtProperties;
import com.example.service.AdminService;
import com.example.service.TeamService;
import com.example.utils.BCryptPasswordEncoderUtils;
import com.example.utils.JwtUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * 管理员业务处理
 **/
@Service
@Slf4j
@DS("master")
@Transactional
public class AdminServiceImpl extends ServiceImpl<AdminMapper, Admin> implements AdminService {

    @Autowired
    private  AdminMapper adminMapper;

    @Autowired
    private TeamService teamService;

    @Autowired
    private JwtProperties jwtProperties;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private AuthenticationManager authenticationManager;

    public void add(Admin admin) {
        //重写父类保存方法
        if (StrUtil.isBlank(admin.getName())){
            admin.setName(admin.getUsername());
        }
        if (StrUtil.isBlank(admin.getPassword())){
            admin.setPassword("123456");
        }
        admin.setIsDeleted(0);
        admin.setVersion(0);
        adminMapper.insert(admin);
    }

    /**
     * 删除
     */
    public void deleteById(Integer id) {
        Admin admin = selectById(id);
        admin.setIsDeleted(1);
        updateAdmin(admin);
    }

    /**
     * 批量删除
     */
    public void deleteBatch(List<Integer> ids) {
        for (Integer id : ids) {
            Admin admin = selectById(id);
            admin.setIsDeleted(1);
            updateAdmin(admin);
        }
    }

    /**
     * 修改
     */
    public void updateAdmin(Admin admin) {
        adminMapper.updateById(admin);
    }

    /**
     * 根据ID查询
     */
    public Admin selectById(Integer id) {
        Admin admin = adminMapper.selectById(id);
        if (admin.getTeamId() != null){
            admin.setTeamName(teamService.selectById(admin.getTeamId()).getName());
        }
        return admin;
    }

    /**
     * 查询所有
     */
    public List<Admin> selectAll(Admin admin) {
        QueryWrapper<Admin> queryWrapper = new QueryWrapper<>();
        queryWrapper.like(StrUtil.isNotBlank(admin.getUsername()),"username",admin.getUsername());
        queryWrapper.eq("is_deleted",0);
        return adminMapper.selectList(queryWrapper);
    }

    /**
     * 分页查询
     */
    public Page<Admin> selectPage(Admin admin, Integer pageNum, Integer pageSize) {
        QueryWrapper<Admin> queryWrapper = new QueryWrapper<>();
        queryWrapper.like(StrUtil.isNotBlank(admin.getUsername()),"username",admin.getUsername());
        queryWrapper.eq("is_deleted",0);

        return page(new Page<>(pageNum, pageSize), queryWrapper);
    }

    public Admin selectByUsername(String username){
        QueryWrapper<Admin> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("username",username);
        return adminMapper.selectOne(queryWrapper);
    }

    /**
     * 登录
     */
    public Admin login(Admin admin) {

        UsernameAuthenticationToken authenticationToken = new UsernameAuthenticationToken(admin.getUsername(), admin.getPassword());
        Authentication authenticate = authenticationManager.authenticate(authenticationToken);
        if (ObjectUtil.isNull(authenticate)) {
            throw new CustomException(ResultCodeEnum.USER_ACCOUNT_ERROR);
        }

        //认证通过 生成token
        LoginUser loginUser = (LoginUser) authenticate.getPrincipal();
        Integer userId = loginUser.getAdmin().getId();
        Map<String, Object> claims = new HashMap<>();
        claims.put(JwtClaimsConstant.ADMIN_ID, userId);
        claims.put(JwtClaimsConstant.USERNAME, loginUser.getUsername());
        String token = JwtUtil.createJWT(
                jwtProperties.getAdminSecretKey(),
                jwtProperties.getAdminTtl(),
                claims
        );

        Admin dbAdmin = loginUser.getAdmin();
        dbAdmin.setToken(token);

        //认证通过 存入redis
        redisTemplate.opsForValue().set(KeyEnum.TOKEN + "_" + userId, JSONUtil.toJsonStr(loginUser.getAdmin()));
        redisTemplate.expire(KeyEnum.TOKEN + "_" + userId, 4, TimeUnit.HOURS);
        return dbAdmin;
    }

    /**
     * 注册
     */
    public void register(Account account) {
        Admin admin = new Admin();
        BeanUtils.copyProperties(account, admin);
        add(admin);
    }

    /**
     * 修改密码
     */
    public void updatePassword(Admin dbAdmin, PasswordDTO passwordDTO) {
        dbAdmin.setPassword(BCryptPasswordEncoderUtils.encodePassword(passwordDTO.getPasswordNew()));
        adminMapper.updateById(dbAdmin);
    }

    /**'
     * 根据用户id集合获取用户分页数据
     */
    public Page<Admin> getByPageIds(String ids, String name, Integer pageNum, Integer pageSize) {
        QueryWrapper<Admin> adminQueryWrapper = new QueryWrapper<>();

        ids = ids.substring(ids.indexOf("[")+ 1 , ids.lastIndexOf("]"));
        String[] split = ids.split(",");

        List<Integer> userIds = new ArrayList<>();
        for (String s : split) {
            userIds.add(Integer.valueOf(s));
        }

        adminQueryWrapper
                .eq("is_deleted", 0)
                .like(StringUtils.hasLength(name), "name", name)
                .in("id", userIds);

        Page<Admin> page = adminMapper.selectPage(new Page<>(pageNum, pageSize), adminQueryWrapper);

        return page;
    }

}
